package com.example.zyl.common.utils;

import cn.hutool.extra.spring.SpringUtil;
import com.example.zyl.common.config.MinioConfig;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.Result;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class MinioUtils {

    private static final MinioConfig minioConfig = SpringUtil.getBean(MinioConfig.class);

    public static final String bucket = "my-bucket";

    /**
     * 上传
     *
     * @param multipartFile 文件
     * @return 访问路径
     */
    public static String upload(MultipartFile multipartFile) {
        // bucket 不存在，创建
        try {
            if (!minioConfig.minioClient().bucketExists(bucket)) {
                log.info("创建bucket：" + bucket);
                minioConfig.minioClient().makeBucket(bucket);
            }
            try (InputStream inputStream = multipartFile.getInputStream(); ServerSocket serverSocket = new ServerSocket()) {
                // 上传文件的名称
                String fileName = multipartFile.getOriginalFilename();
                // PutObjectOptions，上传配置(文件大小，内存中文件分片大小)
                PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
                // 文件的ContentType
                putObjectOptions.setContentType(multipartFile.getContentType());
                minioConfig.minioClient().putObject(bucket, fileName, inputStream, putObjectOptions);
                // 返回访问路径

                // 获取本地主机的IP地址
                InetAddress localHost = InetAddress.getLocalHost();
                //String ipAddress = localHost.getHostAddress();
                //String property = SpringUtil.getProperty("server.port");
                String objectUrl1 = getObjectUrl(bucket, fileName);

                //String objectUrl = "http://" + ipAddress + ":" + property + "/sysMinio/download/";
                log.info("上传成功, 文件名 ===> {}, 访问路径 ===>：{}", fileName, objectUrl1);
                return objectUrl1;
            }
        } catch (Exception e) {
            log.error("上传失败，失败原因 ===> {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 文件下载
     */
    public static void download(String fileName, HttpServletResponse response) {
        // 从链接中得到文件名
        InputStream inputStream;
        try {
            MinioClient minioClient = minioConfig.minioClient();
            ObjectStat stat = minioClient.statObject(bucket, fileName);
            inputStream = minioClient.getObject(bucket, fileName);
            response.setContentType(stat.contentType());
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) > 0) {
                response.getOutputStream().write(buffer, 0, length);
            }
            inputStream.close();
            log.info("下载成功, 文件名 ===> {}", fileName);
        } catch (Exception e) {
            log.error("下载失败, 文件名 ===> {} 失败原因 ===> {}", fileName, e.getMessage(), e);
        }
    }


    /**
     * 列出所有存储桶名称
     *
     * @return 存储桶名称列表
     */
    public static List<String> listBucketNames()
            throws Exception {
        List<Bucket> bucketList = listBuckets();
        List<String> bucketListName = new ArrayList<>();
        for (Bucket bucket : bucketList) {
            bucketListName.add(bucket.name());
        }
        return bucketListName;
    }


    /**
     * 查看所有桶
     *
     * @return 存储桶列表
     */
    public static List<Bucket> listBuckets()
            throws Exception {
        return minioConfig.minioClient().listBuckets();
    }


    /**
     * 检查存储桶是否存在
     *
     * @param bucketName 存储桶名称
     * @return 是否存在
     */
    public static boolean bucketExists(String bucketName) throws Exception {
        return minioConfig.minioClient().bucketExists(bucketName);
    }


    /**
     * 创建存储桶
     *
     * @param bucketName 存储桶名称
     * @return 是否创建成功
     */
    public static boolean makeBucket(String bucketName)
            throws Exception {
        boolean flag = bucketExists(bucketName);
        if (!flag) {
            minioConfig.minioClient().makeBucket(bucketName);
            return true;
        } else {
            return false;
        }
    }


    /**
     * 删除桶
     *
     * @param bucketName 存储桶名称
     * @return 是否删除成功
     */
    public static boolean removeBucket(String bucketName)
            throws Exception {
        boolean flag = bucketExists(bucketName);
        if (flag) {
            Iterable<Result<Item>> myObjects = listObjects(bucketName);
            if (myObjects != null) {
                for (Result<Item> result : myObjects) {
                    Item item = result.get();
                    // 有对象文件，则删除失败
                    if (item.size() > 0) {
                        return false;
                    }
                }
            }
            // 删除存储桶，注意，只有存储桶为空时才能删除成功。
            minioConfig.minioClient().removeBucket(bucketName);
            flag = bucketExists(bucketName);
            return !flag;
        }
        return false;
    }


    /**
     * 列出存储桶中的所有对象
     *
     * @param bucketName 存储桶名称
     */
    public static Iterable<Result<Item>> listObjects(String bucketName) throws Exception {
        boolean flag = bucketExists(bucketName);
        if (flag) {
            return minioConfig.minioClient().listObjects(bucketName);
        }
        return null;
    }


    /**
     * 列出存储桶中的所有对象名称
     *
     * @param bucketName 存储桶名称
     * @return 对象名称列表
     */
    public static List<String> listObjectNames(String bucketName) throws Exception {
        List<String> listObjectNames = new ArrayList<>();
        boolean flag = bucketExists(bucketName);
        if (flag) {
            Iterable<Result<Item>> myObjects = listObjects(bucketName);
            if (myObjects != null) {
                for (Result<Item> result : myObjects) {
                    Item item = result.get();
                    listObjectNames.add(item.objectName());
                }
            }
        }
        return listObjectNames;
    }


    /**
     * 删除一个对象
     *
     * @param bucketName 存储桶名称
     * @param objectName 存储桶里的对象名称
     * @return 是否删除成功
     */
    public static boolean removeObject(String bucketName, String objectName) throws Exception {
        boolean flag = bucketExists(bucketName);
        if (flag) {
            List<String> objectList = listObjectNames(bucketName);
            for (String s : objectList) {
                if (s.equals(objectName)) {
                    minioConfig.minioClient().removeObject(bucketName, objectName);
                    return true;
                }
            }
        }
        return false;
    }


    /**
     * 文件访问路径
     *
     * @param bucketName 存储桶名称
     * @param objectName 存储桶里的对象名称
     * @return 访问路径
     */
    public static String getObjectUrl(String bucketName, String objectName) throws Exception {
        boolean flag = bucketExists(bucketName);
        String url = "";
        if (flag) {

            url = minioConfig.minioClient().presignedGetObject(bucketName, objectName);
        }
        return url;
    }

}
